// 3.封装函数，主要是为了对单个数据做数据劫持
function defineReactive(_data, key, value) {
    // 把value值在交给observe方法，进行深层次的数据响应式
    observe(value)
    
    Object.defineProperty(_data, key, {
        get() {
            console.log('正在获取' + key + '的值', '收集所有依赖项watcher');
            return value
        },
        set(newVal) {
            if (newVal === value) return

            console.log('正在设置' + key + '的值', '通知所有的watcher进行更新');
            value = newVal
        }
    })
}

// 3.封装一个Observer类，主要用来处理发布订阅模式的核心操作
// 响应式操作：收集依赖，通知更新
class Observer {
    constructor(_data) {
        this._data = _data

        // 判断当前的_data是对象还是数组
        if (Array.isArray(_data)) {
            this.observeArray(_data)
        } else {
            this.walk(_data)
        }
    }

    // 在Observer的原型对象上封装一个对数组操作的方法
    observeArray(_data) {
        _data.forEach(item => {
            observe(item)
        })
    }

    // 在Observer的原型对象上封装一个对对象操作的方法
    walk(_data) {
        for (let key of Object.keys(_data)) {
            // 把每一个数据的响应式核心代码交给defineReactive函数处理
            defineReactive(_data, key, _data[key])
        }
    }
}


// 2. 封装一个observe函数，接收_data，遍历_data的值，一个个的进行数据劫持
function observe(_data) {
    if (typeof _data !== 'object' || _data === null) return

    new Observer(_data)
    // for (let key of Object.keys(_data)) {
    //     // 把每一个数据的响应式核心代码交给defineReactive函数处理
    //     defineReactive(_data, key, _data[key])
    // }
}


// 1.封装一个Vue的构造函数
function Vue(options) {
    this._data = options.data

    // 数据代理，把_data中的属性取出来，一个个放在vue实例上
    for (let key of Object.keys(this._data)) {
        Object.defineProperty(this, key, {
            get() {
                return this._data[key]
            },
            set(newVal) {
                this._data[key] = newVal
            }
        })
    }

    // 拿到_data的数据开始进行响应式操作，
    observe(this._data)
}

// 实例化
const vm = new Vue({
    data: {
        count: 1,
        course: {
            type: 'easy',
            name: 'html'
        }
    }
})


console.log(vm);

function huoqu() {
    console.log(vm.count);
}

function shezhi() {
    vm.count++;
}

// huoqu();
shezhi();